package com.ymt.bpm.service.platform.biz.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ymt.bpm.dao.MongoDao;
import com.ymt.bpm.service.platform.biz.BizDataService;
import com.ymt.bpm.util.Const;
import com.ymt.bpm.util.DateUtil;
import com.ymt.bpm.util.DhxUtil;
import com.ymt.fmd.model.PBizDocM;
import com.ymt.fmd.model.PBizDocS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import static org.springframework.data.mongodb.core.query.Criteria.where;

import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;


@Service
public class BizDataServiceImpl implements BizDataService {

    /**
     * Logger
     */
    private Logger log = LoggerFactory.getLogger(this.getClass());

    public static final String SHARED_ID = "sharedId";

    @Autowired
    private MongoDao mgdao;

    @Override
    public JSONObject queryDhx(String tenantId, String appId,
                            int frowRow, int toRow,
                            String model, String colsStr,
                            String ordercolumnsStr,
                            String lang, int timezoneOffset,
                            String searchkey, String conditionsStr) {
        JSONObject rtn = new JSONObject();
        JSONArray rows = new JSONArray();
        String collectionName = getCollectionName(tenantId, appId, model, '0');

        Query query = new Query();
        // add search key
        if (searchkey!=null && searchkey.length()>0) {
            query.addCriteria(where("searchText").regex("/"+searchkey+"/"));
        }
        // add conditions
        if (conditionsStr!=null && conditionsStr.length()>0) {
            JSONArray conditions = JSONArray.parseArray(conditionsStr);
            if (conditions.size()>0) {
                for (int i=0; i<conditions.size(); i++) {
                    JSONObject condition = conditions.getJSONObject(i);
                    query.addCriteria(where(condition.getString("key")).is(condition.getString("value")));
                }
            }
        }

        //count
        long count = mgdao.count(collectionName, query, PBizDocM.class);

        //add order by
        JSONArray ocs = JSONArray.parseArray(ordercolumnsStr);
        List<Sort> sorts = new ArrayList<Sort>();
        if (ocs!=null && ocs.size()>0) {
            for (int i=0; i<ocs.size(); i++) {
                JSONObject o = ocs.getJSONObject(i);
                String col = o.keySet().iterator().next();
                sorts.add(new Sort(Sort.Direction.fromString(o.getString(col)), "data."+col));
                if (i>1) {
                    break; //use 2 columns at most
                }
            }
        }

        //query
        List<PBizDocM> list = mgdao.findPage(collectionName, query, PBizDocM.class, frowRow, toRow, sorts);
        String[] cols = StringUtils.commaDelimitedListToStringArray(colsStr);
        if (list!=null && list.size()>0 && cols!=null && cols.length>0) {
            int rowid = 1;
            for (PBizDocM biz : list) {
                JSONObject row = new JSONObject();
                JSONArray data = new JSONArray();
                data.add(0);
                data.add(0);
                data.add(frowRow - 1 + rowid);
                data.add(biz.getSharedId());
                for (String col : cols) {
                    data.add(biz.getData().get(col));
                }
                row.put(DhxUtil.DATA, data);
                row.put(DhxUtil.ID, rowid++);
                rows.add(row);
            }
        }

        rtn.put(DhxUtil.POS, frowRow - 1);
        rtn.put(DhxUtil.ROWS, rows);
        rtn.put(DhxUtil.TOTAL_COUNT, count);
        return rtn;
    }

    @Override
    public JSONObject get(String tenantId, String appId, String models, String sharedId, int timezoneOffset) {
        JSONObject rtn = new JSONObject();
        String[] modelArr = models.split(";");
        Query query = new Query(where(SHARED_ID).is(sharedId));
        JSONObject nullObj = new JSONObject();
        for (String model : modelArr) {
//            if ("none".equalsIgnoreCase(sharedId)) {
//                rtn.put(model, nullObj);
//            } else {
                String collectionName = getCollectionName(tenantId, appId, model, '0');
                PBizDocM entity = mgdao.findOne(collectionName, query, PBizDocM.class);
                //bo.put("createTime", DateUtil.getDateByStr(bo.getString("createTime")));
                //bo.put("updateTime", DateUtil.getDateByStr(bo.getString("updateTime")));
                if (entity==null) {
                    rtn.put(model, nullObj);
                } else {
                    rtn.put(model, entity.getData());
                }
//            }
        }
        return rtn;
    }

    @Override
    public JSONObject save(String tenantId, String appId, String data, String sharedId, String loginName, String displayName) {
        JSONObject models = JSONObject.parseObject(data);
        JSONObject rtn = new JSONObject();
        int rs = 0;
        Query query = new Query(where(SHARED_ID).is(sharedId));
        for (String model : models.keySet()) {
            String collectionName = getCollectionName(tenantId, appId, model, '0');
            JSONObject modelVals = models.getJSONObject(model);
            JSONObject modelData = new JSONObject();
            StringBuilder search = new StringBuilder();
            for (String attr : modelVals.keySet()) {
                String value = modelVals.getJSONObject(attr).getString("value");
                if (value!=null && value.length()>0) {
                    modelData.put(attr, value);
                    search.append("|").append(value.toUpperCase());
                }
            }
            PBizDocM entity = mgdao.findOne(collectionName, query, PBizDocM.class);
            if (entity==null) {
                entity = new PBizDocM();
                entity.setSharedId(sharedId);
                entity.setCreateTime(DateUtil.getGMTDate());
                entity.setCreator(loginName);
                entity.setCreatorName(displayName);
            }
            entity.setData(modelData);
            entity.setSearchText(search.toString());
            entity.setUpdateTime(DateUtil.getGMTDate());
            entity.setUpdator(loginName);
            entity.setUpdatorName(displayName);

            mgdao.save(collectionName, entity);
            rs ++;
        }
        rtn.put(Const.AJAX_RESULT, rs);
        return rtn;
    }

    @Override
    public JSONObject delete(String tenantId, String appId,
                             String models0, String models1, String sharedIds,
                             String loginName, String displayName) {
        int rs = 0;
        String[] sharedIdArr = sharedIds.split(",");
        JSONArray m0arr = JSONArray.parseArray(models0);
        JSONArray m1arr = JSONArray.parseArray(models1);
        for (String sharedId : sharedIdArr) {
            Query query = new Query(where(SHARED_ID).is(sharedId));
            if (m0arr!=null && m0arr.size()>0) {
                for (int i=0; i<m0arr.size(); i++) {
                    String collectionName = getCollectionName(tenantId, appId, m0arr.getString(i), '0');
                    mgdao.delete(collectionName, query, PBizDocM.class);
                }
                rs += m0arr.size();
            }
            if (m1arr!=null && m1arr.size()>0) {
                for (int i=0; i<m1arr.size(); i++) {
                    String collectionName = getCollectionName(tenantId, appId, m1arr.getString(i), '1');
                    mgdao.delete(collectionName, query, PBizDocS.class);
                }
                rs += m1arr.size();
            }
        }

        JSONObject rtn = new JSONObject();
        rtn.put(Const.AJAX_RESULT, rs);
        return rtn;
    }

    @Override
    public JSONObject querySubAllDhx(String tenantId, String appId, String paramStr, String sharedId) {
        JSONObject param = JSONObject.parseObject(paramStr);
        String model = param.getString("model");
        JSONArray columns = param.getJSONArray("columns");
        String collectionName = getCollectionName(tenantId, appId, model, '1');
        Query query = new Query(where(SHARED_ID).is(sharedId)).limit(1000); //TODO max
        List<PBizDocS> list = mgdao.find(collectionName, query, PBizDocS.class);
        JSONObject rtn = new JSONObject();
        rtn.put(DhxUtil.POS, 0);
        if (list!=null && list.size()>0) {
            JSONArray rows = new JSONArray();
            int rowid = 1;
            for (PBizDocS doc : list) {
                JSONObject row = new JSONObject();
                JSONArray data = new JSONArray();
                data.add(doc.getItemNo());
                if (columns!=null && columns.size()>0) {
                    for (int i=0; i<columns.size(); i++) {
                        data.add(doc.getData().get(columns.getString(i)));
                    }
                }
                row.put(DhxUtil.ID, rowid++);
                row.put(DhxUtil.DATA, data);
                rows.add(row);
            }
            rtn.put(DhxUtil.TOTAL_COUNT, list.size());
            rtn.put(DhxUtil.ROWS, rows);
        } else {
            rtn.put(DhxUtil.ROWS, new JSONArray());
        }
        return rtn;
    }

    @Override
    public JSONObject saveSubAllDhx(String tenantId, String appId, String paramStr, String sharedId) {
        JSONObject rtn = new JSONObject();
        JSONObject param = JSONObject.parseObject(paramStr);
        String model = param.getJSONObject("models").getString("model");
        //JSONObject modelAttrs = param.getJSONObject("models").getJSONObject("modelAttrs");
        JSONObject colIndex = param.getJSONObject("colIndex");
        JSONArray rows = param.getJSONArray("rows");
        String collectionName = getCollectionName(tenantId, appId, model, '1');
        Query query = new Query(where(SHARED_ID).is(sharedId));
        int rs = mgdao.delete(collectionName, query, PBizDocS.class);
        if (rows!=null && rows.size()>0) {
            List<PBizDocS> list = new ArrayList<PBizDocS>();
            for (int i=0; i<rows.size(); i++) {
                PBizDocS doc = new PBizDocS();
                doc.setSharedId(sharedId);
                doc.setModel(model);
                doc.setItemNo(rows.getJSONArray(i).getInteger(colIndex.getInteger("ITEM_NO_")));
                JSONObject data = new JSONObject();
                for (String col : colIndex.keySet()) {
                    if ("ITEM_NO_".equals(col)) {
                        continue;
                    }
                    data.put(col, rows.getJSONArray(i).get(colIndex.getInteger(col)));
                }
                doc.setData(data);
                list.add(doc);
                rs ++;
            }
            mgdao.batchInert(collectionName, list);
        }
        rtn.put(Const.AJAX_RESULT, rs);
        return rtn;
    }

    /**
     * 生成Collection name
     * @param tenantId
     * @param appId
     * @param model
     * @param purpose
     * @return
     */
    private String getCollectionName(String tenantId, String appId, String model, char purpose) {
        StringBuilder sb = new StringBuilder();
        sb.append('C')
            .append(purpose)
            .append('_')
            .append(tenantId!=null && tenantId.length()>0 ? tenantId : '0')
            .append('_')
            .append(appId!=null && appId.length()>0 ? appId : '0')
            .append('_')
            .append(model.toUpperCase());
        if (log.isDebugEnabled()) {
            log.debug("collectionName="+sb);
        }
        return sb.toString();
    }

}
